#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <future>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <signal.h>

#define MAXLINE 8192
#define UDPPORT 8001
#define SERVERIP "172.17.2.2"
std::atomic_bool running(true);
int confd;
using namespace std;
void signalHandle(int sig)
{
    if (sig == SIGINT)
    {
        std::cout << "关闭套接字体" << std::endl;
        running = false;
        close(confd);
        exit(1);
    }
}


int main()
{
    signal(SIGINT, signalHandle);

    unsigned int addr_length;

    struct sockaddr_in serveraddr;

    // 1. 使用socket()，生成套接字文件描述符；
    if ((confd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket() error");
        exit(1);
    }

    //2. 通过struct sockaddr_in 结构设置服务器地址和监听端口；
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(SERVERIP);
    serveraddr.sin_port = htons(UDPPORT);
    addr_length = sizeof(serveraddr);

    //3. 需要与主机长时间通信时提高效率(通过减少第1，3步骤)
    // (1). 向udp套接字注册目标ip和端口号
    // (2). 传输数据
    // (3). 删除套接字中的目标ip和端口号
    connect(confd, (struct sockaddr *)&serveraddr, addr_length);

    // 向服务器发送数据，sendto() ；
    std::string send_data;
    int send_length = 0;
    auto send_thread = std::async(std::launch::async, [&]
                                  {
    int i = 0;
    while (running)
    {
        send_data = std::string("我是客户端, 这是我发的数据: ") + std::to_string(i++);
        send_length = sendto(confd, send_data.c_str(), send_data.length(), 0, (struct sockaddr *)&serveraddr, addr_length);
       std::cout << "\033[1;32m" << "我是客户端，已发出数据: " << send_data << "\033[m" << std::endl;
        //std::cout << "客户端发送数据" << std::endl;
        // if (send_length < 0)
        // {
        //     perror("sendto() error");
        //     exit(1);
        // }
        // cout << "send_length = " << send_length << endl;
        sleep(1);
    } });

    //4. 接收服务器的数据，recvfrom() ；
    char recvline[MAXLINE];
    int recv_length = 0;

    auto recv_thread = std::async(std::launch::async, [&]
                                  {
    while (running)
    {
        std::cout << "等待服务端数据到达..." << std::endl;
        recv_length = recvfrom(confd, recvline, sizeof(recvline), MSG_DONTWAIT, (struct sockaddr *)&serveraddr, &addr_length);
        if(recv_length != -1)
        {
          std::cout << recvline  <<  std::endl;
        }
        else
        {
           std::cout << recv_length << std::endl;
        }
        sleep(1);
    } });

    //5. 关闭套接字，close() ；
    // close(confd);

    return 0;
}